package com.FQJ.stock.server.impl;

import com.FQJ.stock.constant.CodeType;
import com.FQJ.stock.mapper.StockBlockRtInfoMapper;
import com.FQJ.stock.mapper.StockBusinessMapper;
import com.FQJ.stock.mapper.StockMarketIndexInfoMapper;
import com.FQJ.stock.mapper.StockRtInfoMapper;
import com.FQJ.stock.pojo.entity.StockBlockRtInfo;
import com.FQJ.stock.pojo.entity.StockMarketIndexInfo;
import com.FQJ.stock.pojo.vo.StockInfoConfig;
import com.FQJ.stock.server.StockTimerTaskService;
import com.FQJ.stock.utils.DateTimeUtil;
import com.FQJ.stock.utils.IdWorker;
import com.FQJ.stock.utils.ParserStockInfoUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Author 付前锦
 * @Package com.FQJ.stock.server.impl
 * @Date 2024/8/9 15:33
 * @description:
 */
@Service
@Slf4j
public class StockTimerTaskServiceImpl implements StockTimerTaskService {
	@Autowired
	private RestTemplate restTemplate;
	@Autowired
	private StockInfoConfig stockInfoConfig;
	@Autowired
	private IdWorker idWorker;
	@Autowired
	private ParserStockInfoUtil parserStockInfoUtil;

	@Autowired
	private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
	@Autowired
	private StockBusinessMapper stockBusinessMapper;
	@Autowired
	private StockRtInfoMapper stockRtInfoMapper;
	@Autowired
	private StockBlockRtInfoMapper stockBlockRtInfoMapper;

	@Autowired
	private RabbitTemplate rabbitTemplate;

	/**
	 * 获得国内大盘实时数据
	 */
	@Override
	public void getStockTimerTaskService() {
		//1.定义采集的url接口
		String url = stockInfoConfig.getMarketUrl() + String.join(",", stockInfoConfig.getInner());
		//2.调用restTemplate采集数据
		//设置请求头参数
		HttpHeaders headers = new HttpHeaders();
		headers.add("Referer", "https://finance.sina.com.cn/stock/");
		headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36" +
				" (KHTML,like Gecko) Chrome/72.0.3626.121 Safari/537.36");
		//请求头填充到请求对象下
		HttpEntity<Map> entry = new HttpEntity<>(headers);
		//发送请求,是get请求，看得csdn文档是post请求。get请求可以用post,但post不能用get好像
		ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, entry, String.class);
		int code = responseEntity.getStatusCodeValue();
		if (code != 200) {
			//当前请求失败
			log.error("当前时间点：{}，采集数据失败，HTTP状态码：{}", DateTime.now().toString("yyyy-MM-dd HH:mm:ss")
					, code);
		}
		String reg = "var hq_str_(.+)=\"(.+)\";";
		//编译表达式,获取编译对象
		Pattern pattern = Pattern.compile(reg);
		//匹配字符串
		Matcher matcher = pattern.matcher(responseEntity.getBody());
		ArrayList<StockMarketIndexInfo> list = new ArrayList<>();
		//判断是否有匹配的数值
		while (matcher.find()) {
			//获取大盘的code
			String marketCode = matcher.group(1);
			//获取其它信息，字符串以逗号间隔
			String otherInfo = matcher.group(2);
			//以逗号切割字符串，形成数组
			String[] splitArr = otherInfo.split(",");
			//大盘名称
			String marketName = splitArr[0];
			//获取当前大盘的开盘点数
			BigDecimal openPoint = new BigDecimal(splitArr[1]);
			//前收盘点
			BigDecimal preClosePoint = new BigDecimal(splitArr[2]);
			//获取大盘的当前点数
			BigDecimal curPoint = new BigDecimal(splitArr[3]);
			//获取大盘最高点
			BigDecimal maxPoint = new BigDecimal(splitArr[4]);
			//获取大盘的最低点
			BigDecimal minPoint = new BigDecimal(splitArr[5]);
			//获取成交量
			Long tradeAmt = Long.valueOf(splitArr[8]);
			//获取成交金额
			BigDecimal tradeVol = new BigDecimal(splitArr[9]);
			//时间
			Date curTime = DateTimeUtil.getDateTimeWithoutSecond(splitArr[30] + " " + splitArr[31]).toDate();
			//组装entity对象
			StockMarketIndexInfo info = StockMarketIndexInfo.builder()
					.id(idWorker.nextId())
					.marketCode(marketCode)
					.marketName(marketName)
					.curPoint(curPoint)
					.openPoint(openPoint)
					.preClosePoint(preClosePoint)
					.maxPoint(maxPoint)
					.minPoint(minPoint)
					.tradeVolume(tradeVol)
					.tradeAmount(tradeAmt)
					.curTime(curTime)
					.build();
			//收集封装的对象，方便批量插入
			list.add(info);
		}
		log.info("采集的当前大盘数据：{}", list);
		if (CollectionUtils.isEmpty(list)) {
			log.error("这是一个集合工具类判断，list为空");
		}
		int count = stockMarketIndexInfoMapper.insetBatch(list);
		if (count > 0) {
			//通知后台终端刷新本地缓存，发送的日期数据是告知对方当前更新的股票数据所在时间点
			rabbitTemplate.convertAndSend("stockExchange","inner.market",new Date());
			log.info("当前时间：{},插入数据：{}成功", DateTime.now(), list);
		} else {
			log.info("当前时间：{},插入数据：{}成功", DateTime.now(), list);
		}
	}

	/**
	 * 批量获取个股股票分时数据详情信息
	 * http://hq.sinajs.cn/list=sz000002,sh600015
	 */
	@Override
	public void getStockRtIndex() {
		List<String> stockIds = stockBusinessMapper.getStockIds();
		List<String> collect = stockIds.stream().map(string -> {
			return string.startsWith("0") ? "sz" + string : "sh" + string;
		}).collect(Collectors.toList());
		//设置公共请求头对象
		//设置请求头数据
		HttpHeaders headers = new HttpHeaders();
		headers.add("Referer", "https://finance.sina.com.cn/stock/");
		headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
		HttpEntity<String> entity = new HttpEntity<>(headers);

		/**
		 * [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
		 * [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
		 * [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45]
		 * [46, 47, 48, 49, 50]
		 */
		Lists.partition(collect, 20).forEach(item -> {
			String url = stockInfoConfig.getMarketUrl() + String.join(",", item);
			ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
			List list = parserStockInfoUtil.parser4StockOrMarketInfo(responseEntity.getBody(), CodeType.ASHARE);
			log.info("封装的数据：{}", list);
			stockRtInfoMapper.insertBatch(list);
		});

	}

	/**
	 * 采集模块数据
	 */
	@Override
	public void getStockBlockRtInfo() {
		//https://vip.stock.finance.sina.com.cn/q/view/newSinaHy.php
		//使用restTemplate拉取数据
		String url = "https://vip.stock.finance.sina.com.cn/q/view/newSinaHy.php";
        /*
          参数1：url请求地址
          参数2：请求返回的数据类型
         */
		ResponseEntity<String> result = restTemplate.getForEntity(url, String.class);

		//响应数据
		String respData = result.getBody();
		List<StockBlockRtInfo> lists = parserStockInfoUtil.parse4StockBlock(respData);
		int count=stockBlockRtInfoMapper.insertBath(lists);
		log.info("插入了：{}条数据",count);
	}
}
